﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Diagnostics;
using System.IO;


using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure.Storage.Blob;

public abstract class AzureStorageHelper
{
    protected static CloudStorageAccount storageAccount
    {
        get
        {
            // Retrieve the storage account from the connection string.
            string connectionString = RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString");

            try
            {
                if (connectionString.Equals("UseDevelopmentStorage=true"))
                    return CloudStorageAccount.DevelopmentStorageAccount;
                else
                    return CloudStorageAccount.Parse(connectionString);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                return null;
            }
        }
    }
}

public class AzureTableHelper : AzureStorageHelper
{
    public static bool CheckTableExistence(string tableName)
    {
        if (GetCloudTable(tableName).Exists())
        {
            Trace.WriteLine("Table exists.");
            return true;
        }
        else
        {
            Trace.WriteLine("Table does not exist.");
            return false;
        }
    }

    public static CloudTable GetCloudTable(string tableName)
    {       
        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
        // Create the CloudTable object that represents the "people" table.
        return tableClient.GetTableReference(tableName);
    }

    public static void CreateTable(string tableName)
    {
        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

        // Create the table if it doesn't exist.
        CloudTable table = tableClient.GetTableReference(tableName);
        table.CreateIfNotExists();
    }

    public static void InsertEntity(ITableEntity entity, CloudTable table)
    {
        // Create the TableOperation that inserts the customer entity.
        TableOperation insertOperation = TableOperation.Insert(entity);

        // Execute the insert operation.
        table.Execute(insertOperation);
    }

    public static void InsertEntity(string tableName, ITableEntity entity)
    {
        // Create the CloudTable object that represents the "people" table.
        CloudTable table = AzureTableHelper.GetCloudTable(tableName);

        // Create the TableOperation that inserts the customer entity.
        TableOperation insertOperation = TableOperation.Insert(entity);

        // Execute the insert operation.
        table.Execute(insertOperation);
    }

    public static IEnumerable<T> RetrieveAllEntities<T>(CloudTable table) where T:ITableEntity, new()
    {
        return table.ExecuteQuery<T>(new TableQuery<T>());
    }

    //public static void RetrieveSingleEntity()
    //{
    //    // Retrieve the storage account from the connection string.
    //    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    //        CloudConfigurationManager.GetSetting("StorageConnectionString"));

    //    // Create the table client.
    //    CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

    //    // Create the CloudTable ojbect that represents the "people" table.
    //    CloudTable table = tableClient.GetTableReference("people");

    //    // Create a retrieve operation that takes a customer entity.
    //    TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

    //    // Execute the retrieve operation.
    //    TableResult retrievedResult = table.Execute(retrieveOperation);

    //    // Print the phone number of the result.
    //    if (retrievedResult.Result != null)
    //    {
    //        Console.WriteLine(((CustomerEntity)retrievedResult.Result).PhoneNumber);
    //    }
    //    else
    //    {
    //        Console.WriteLine("The phone number could not be retrieved.");
    //    }
    //}

    public static void DeleteEntity(CloudTable table, ITableEntity deleteEntity)
    {
        // Create the Delete TableOperation.
        if (deleteEntity != null)
        {
            TableOperation deleteOperation = TableOperation.Delete(deleteEntity);

            // Execute the operation.
            table.Execute(deleteOperation);

            Console.WriteLine("Entity deleted.");
            Trace.WriteLine("Entity deleted.");
        }

        else
        {
            Console.WriteLine("Could not retrieve the entity.");
            Trace.WriteLine("Could not retrieve the entity.");
        }
    }

    public static void DeleteTable(string tableName)
    {
        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

        // Create the table if it doesn't exist.
        CloudTable table = tableClient.GetTableReference(tableName);

        // Delete the table it if exists.
        table.DeleteIfExists();
    }

}

public class AzureBlobHelper : AzureStorageHelper
{
    public static CloudBlobContainer GetContainerReference(string containerName)
    {
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve a reference to a container. 
        return blobClient.GetContainerReference(containerName);
    }

    public static void CreateBlobContainer(string containerName)
    {
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve a reference to a container. 
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);

        // Create the container if it doesn't already exist.
        container.CreateIfNotExists();
    }

    public static void UploadBlobIntoContainer(string containerName, string blobName, string filePath)
    {
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve reference to a previously created container.
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);


        // Retrieve reference to a blob named "myblob".
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);

        // Create or overwrite the "myblob" blob with contents from a local file.
        using (var fileStream = System.IO.File.OpenRead(filePath))
        {
            blockBlob.UploadFromStream(fileStream);
        }
    }

    public static void UploadBlobIntoContainer(string containerName, string blobName, byte[] data)
    {
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve reference to a previously created container.
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);


        // Retrieve reference to a blob named "myblob".
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);

        using (var stream = new MemoryStream(data, writable: false))
        {
            blockBlob.UploadFromStream(stream);
        }
    }

    public static void UploadBlobIntoContainer(CloudBlobContainer containerReference, string blobName, string filePath)
    {
        // Retrieve reference to a blob named "myblob".
        CloudBlockBlob blockBlob = containerReference.GetBlockBlobReference(blobName);

        // Create or overwrite the "myblob" blob with contents from a local file.
        using (var fileStream = System.IO.File.OpenRead(filePath))
        {
            blockBlob.UploadFromStream(fileStream);
        }
    }

    public static void DownloadBlobToPath(CloudBlobContainer cointainerReference, string blobname, string filePath)
    {
        // Retrieve reference to a blob named "photo1.jpg".
        CloudBlockBlob blockBlob = cointainerReference.GetBlockBlobReference(blobname);

        // Save blob contents to a file.
        using (var fileStream = System.IO.File.OpenWrite(filePath + blobname))
        {
            blockBlob.DownloadToStream(fileStream);
        }
    }

    public static byte[] DownloadBlobToByteArray(CloudBlobContainer cointainerReference, string blobname)
    {          
        CloudBlockBlob blockBlob = cointainerReference.GetBlockBlobReference(blobname);

        byte[] result = null;
        using (var memoryStream = new MemoryStream())
        {
            blockBlob.DownloadToStream(memoryStream);
            result = memoryStream.ToArray();
        }

        return result;
    }


    public static bool CheckBlobExists(CloudBlobContainer cointainerReference, string blobname)
    {
        CloudBlockBlob blockBlob = cointainerReference.GetBlockBlobReference(blobname);
        return blockBlob.Exists();
    }


    public static void DeleteBlob(CloudBlobContainer cointainerReference, string blobname)
    {
        // Retrieve reference to a blob named "myblob.txt".
        CloudBlockBlob blockBlob = cointainerReference.GetBlockBlobReference(blobname);

        // Delete the blob.
        if (CheckBlobExists(cointainerReference, blobname))
            blockBlob.Delete();
    }

    public static void DeleteBlob(string containerName, string blobname)
    {
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve a reference to a container. 
        CloudBlobContainer cointainerReference = blobClient.GetContainerReference(containerName);

        // Retrieve reference to a blob named "myblob.txt".
        CloudBlockBlob blockBlob = cointainerReference.GetBlockBlobReference(blobname);

        // Delete the blob.
        if (CheckBlobExists(cointainerReference, blobname))
            blockBlob.Delete();
    }
}
